<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Fake Array</title>
    <script src="libs/jquery.js"></script>
</head>

<body>
    <pre>
        <code>

        </code>
    </pre>
    <script id="">
        /* 伪数组 */
        function FA(len) {
            len = +len || 0;
            this[len-1]=undefined;
            this.length = len;
        }
        // FA.prototype.splice = Array.prototype.splice;
        window.fa = new FA(13)
        console.log(fa)

        /* isEmptyObject */
        /**
         *  empty object的定义是什么
         *  什么是object?
         *  一组属性的集合，{a:1}, {a: {b:1} }......
         *  空对象是不是可以理解为 {}
         *  但是由于js的原型机制，
         *  即使单独写一个对象字面量，也会存在一个指向Object的属性
         */ 
        /**
         * 判断对象是否不为空的条件，是看是否具有可枚举的属性
         * for ... in操作符会遍历对象自身所有可枚举的属性
         * 获取对象所有可枚举属性的方法Object.keys, Object.values
         * Object.entries 返回对象上所有可枚举属性的 [key, value]数组，也能判断对象是否为空
         * Object.getOwnPropertyNames 返回对象自身的所有属性
         */
        // 方法一  Object.keys, Object.values, Object.entries, Object.getOwnPropertyNames
        // function isEmptyObject(o){
        //     return !o || !Object.keys(o).length
        // }
        // 方法二 
        /*  无法处理的情况 1. new Date, 2. function f(){}, */
        // function isEmptyObject(o) {
        //     if( o === null ) return true;
        //     var type = typeof o;
        //     switch(type){
        //         case 'number':
        //         case 'boolean':
        //         case 'symbol':
        //         case 'undefined':
        //             return true;
        //         case 'string':
        //             return !o;
        //         case 'function':
        //             return true;
        //         case 'object':
        //             var str = JSON.stringify(o);
        //             return (str === '[]' || str === '{}') && isEmptyObject(Object.getPrototypeOf(o))
        //     }
        // }

        // 方法三
        function isEmptyObject(o){
            return !o || !o.valueOf();
        }
        function Obj(){}
        Object.defineProperty(Obj.prototype, 'enum', {
            enumerable: true,
            value: 'enumed'
        })
        Object.defineProperty(Obj.prototype, 'notenum', {
            enumerable: false,
            value: 'not enumable'
        })


        /* 测试用例 */
        var d1 = new Date(), d2 = new Date(), f1 = function(){}, f2=function(){}, obj = new Obj(), r1 = /reg/, r2 = /with-proto-foo/;
        r2.foo = d2.foo = f2.foo = "test foo"
        const base=[0, 123, null, undefined, '', 'abc', true, false, Symbol('symbol'), d1, d2, r1, r2, f1, f2, [], [1,2], {}, {k:1, v:2}, obj]

        base.forEach(v=>{
            console.log(v,$.isEmptyObject(v), isEmptyObject(v))
        })        
    </script>

    <script>
        document.querySelector('code').innerHTML = document.body.querySelector('script').innerHTML
    </script>
</body>

</html>